package club.xyes.zkh.ecommerce.service.listener.impl;

import club.xyes.zkh.ecommerce.commons.context.ApplicationConstants;
import club.xyes.zkh.ecommerce.commons.dto.ConsumptionOverview;
import club.xyes.zkh.ecommerce.commons.entity.*;
import club.xyes.zkh.ecommerce.commons.properties.WechatConfigurationProperties;
import club.xyes.zkh.ecommerce.commons.util.DateTimeUtil;
import club.xyes.zkh.ecommerce.commons.util.MoneyUtils;
import club.xyes.zkh.ecommerce.service.*;
import club.xyes.zkh.ecommerce.service.listener.OnCouponGrantListener;
import club.xyes.zkh.ecommerce.service.listener.OnPaymentSuccessListener;
import club.xyes.zkh.ecommerce.service.listener.OnUserMembershipLevelChangedListener;
import club.xyes.zkh.ecommerce.wechat.dto.SendTemplateMsgResult;
import club.xyes.zkh.ecommerce.wechat.dto.TemplateMsgData;
import club.xyes.zkh.ecommerce.wechat.dto.WxAccessToken;
import club.xyes.zkh.ecommerce.wechat.service.WeChatService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Create by 郭文梁 2019/4/26 0026 18:39
 * OnPaymentSuccessListenerImpl
 * 支付成功回调实现
 *
 * @author 郭文梁
 * @data 2019/4/26 0026
 */
@Component
@Slf4j
public class OnPaymentSuccessListenerImpl implements OnPaymentSuccessListener {
    private static final String PAYMENT_SUCCESS_TEMPLATE_MSG_ID = "F61jluryHQGoJux7khGM9AdRtIoelXlPpl2Ow3Pqjjc";
    private final UserMembershipService userMembershipService;
    private final UserService userService;
    private final ShopService shopService;
    private final ShopMembershipLevelService shopMembershipLevelService;
    private final TransactionLogService transactionLogService;
    private final CouponService couponService;
    private final UserCouponService userCouponService;
    private final WeChatService weChatService;
    private final WechatConfigurationProperties wechatConfigurationProperties;
    private final WxFormIdService wxFormIdService;
    private final OnUserMembershipLevelChangedListener onUserMembershipLevelChangedListener;
    private final OnCouponGrantListener onCouponGrantListener;

    @Autowired
    public OnPaymentSuccessListenerImpl(UserMembershipService userMembershipService,
                                        UserService userService,
                                        ShopService shopService,
                                        ShopMembershipLevelService shopMembershipLevelService,
                                        TransactionLogService transactionLogService,
                                        CouponService couponService,
                                        UserCouponService userCouponService,
                                        WeChatService weChatService,
                                        WechatConfigurationProperties wechatConfigurationProperties,
                                        WxFormIdService wxFormIdService,
                                        OnUserMembershipLevelChangedListener onUserMembershipLevelChangedListener,
                                        OnCouponGrantListener onCouponGrantListener) {
        this.userMembershipService = userMembershipService;
        this.userService = userService;
        this.shopService = shopService;
        this.shopMembershipLevelService = shopMembershipLevelService;
        this.transactionLogService = transactionLogService;
        this.couponService = couponService;
        this.userCouponService = userCouponService;
        this.weChatService = weChatService;
        this.wechatConfigurationProperties = wechatConfigurationProperties;
        this.wxFormIdService = wxFormIdService;
        this.onUserMembershipLevelChangedListener = onUserMembershipLevelChangedListener;
        this.onCouponGrantListener = onCouponGrantListener;
    }

    @Override
    public void onPaymentSuccess(TransactionLog transactionLog, Map<String, Object> context) {
        Integer userId = transactionLog.getUserId();
        Integer shopId = transactionLog.getShopId();
        User user = userService.getRequired(userId);
        Shop shop = shopService.getRequired(shopId);
        UserMembership membership = refreshUserMembership(user, shop);
        List<UserCoupon> coupons = grantCoupon(transactionLog, user, shop);
        context.put("membership", membership);
        context.put("coupons", coupons);
//        try {
//            sendNotifyMsg(user, shop, transactionLog);
//        } catch (IOException e) {
//            log.warn("Send payment notify msg error, ", e);
//        }
    }

    /**
     * 发送通知信息
     *
     * @param user           用户
     * @param shop           商铺
     * @param transactionLog 交易记录
     */
    private void sendNotifyMsg(User user, Shop shop, TransactionLog transactionLog) throws IOException {
        String openId = user.getWxOpenId();
        String appId = wechatConfigurationProperties.getUserMicroProgramAppId();
        WxFormId formId = wxFormIdService.popOne(appId, openId);
        if (formId == null) {
            //说明没有多余的formId去发送通知信息
            return;
        }
        String secret = wechatConfigurationProperties.getUserMicroProgramSecret();
        WxAccessToken accessToken = weChatService.getAccessToken(appId, secret);

        Map<String, TemplateMsgData> data = new HashMap<>(5);
        data.put("keyword1", new TemplateMsgData(DateTimeUtil.format(transactionLog.getCreateTime(), ApplicationConstants.DATE_TIME_FORMAT)));
        data.put("keyword2", new TemplateMsgData(MoneyUtils.fen2Yuan(transactionLog.getAmountPayable())));
        data.put("keyword3", new TemplateMsgData(transactionLog.getTradeNo()));
        data.put("keyword4", new TemplateMsgData(shop.getName()));
        data.put("keyword5", new TemplateMsgData(MoneyUtils.fen2Yuan(transactionLog.getActualAmountPaid())));
        Map<String, String> miniProgram = new HashMap<>(2);
        SendTemplateMsgResult sendTemplateMsgResult = weChatService.sendTemplateMsg(appId, accessToken, formId.getFormId(), PAYMENT_SUCCESS_TEMPLATE_MSG_ID, openId, data, miniProgram, null);
        log.debug("Send template msg result{}", sendTemplateMsgResult);
    }

    /**
     * 发放优惠券
     *
     * @param transactionLog 交易记录
     * @param user           用户
     * @param shop           商铺
     */
    private List<UserCoupon> grantCoupon(TransactionLog transactionLog, User user, Shop shop) {
        Integer actualAmountPaid = transactionLog.getActualAmountPaid();
        List<Coupon> coupons = couponService.findPermissionGrantsOfShop(shop, actualAmountPaid);
        if (coupons == null || coupons.size() <= 0) {
            return null;
        }
        List<UserCoupon> grantResult = userCouponService.autoGrant(user, shop, coupons, actualAmountPaid, onCouponGrantListener);
        log.info("Auto coupon grant {}", grantResult);
        return grantResult;
    }

    /**
     * 刷新用户的会员等级
     *
     * @param user 用户
     * @param shop 商铺
     */
    private UserMembership refreshUserMembership(User user, Shop shop) {
        ConsumptionOverview consumptionOverview = transactionLogService.getConsumptionOverview(shop, user);
        ShopMembershipLevel level = shopMembershipLevelService.highestLevelOfMatching(shop, consumptionOverview.getTotalFee(), consumptionOverview.getTimes());
        UserMembership membership = userMembershipService.register(user, shop, level, onUserMembershipLevelChangedListener);
        log.info("Updated membership level:{}", membership);
        return membership;
    }
}
